package com.itdct.onflow.com.itdct.onflow.system.generator.core

import com.itdct.onflow.com.itdct.onflow.system.generator.config.SysGeneratorConfig
import com.itdct.onflow.com.itdct.onflow.system.generator.context.SysGeneratorContext
import com.itdct.onflow.core.entity.IdEntity
import com.itdct.onflow.core.extend.logInfo
import com.itdct.onflow.core.util.TimeUtil
import com.itdct.onflow.generator.base.BaseTemplate
import com.itdct.onflow.generator.core.CodeGenerator
import com.itdct.onflow.generator.core.EntityAnalyse
import com.itdct.onflow.system.api.entity.SysApiEntity
import com.itdct.onflow.system.component.entity.SysComponentEntity
import com.itdct.onflow.system.generator.core.SyncApiCore
import com.itdct.onflow.system.generator.core.SyncApiMenuCore
import com.itdct.onflow.system.generator.core.SyncComponentCore
import com.itdct.onflow.system.generator.core.SyncMenuCore
import com.itdct.onflow.system.menu.entity.SysMenuEntity

/**
 * @author Zhouwx
 * @date 2025/9/8 15:24:19
 * @version 1.0
 * @description
 */
class SystemGenerator(
    override val generatorConfig: SysGeneratorConfig,
    templateClasses: List<Class<out BaseTemplate>>
) : CodeGenerator(generatorConfig, templateClasses) {

    override fun <T : IdEntity> generate(clazz: Class<T>) {
        val entityAnalyse = EntityAnalyse<T>(generatorConfig)
        val context = SysGeneratorContext()
        context.connection = connection
        context.generateTime = TimeUtil.timestampToString(System.currentTimeMillis(), TimeUtil.yyyyMMddHHmmss_HYPHEN)
        val classModel = entityAnalyse.analyseClass(clazz)
        context.classModel = classModel
        val contextPath = generatorConfig.contextPath
        if (!contextPath.startsWith("/")) {
            generatorConfig.contextPath = "/$contextPath"
        }

        val sysMenuEntityAnalyse = EntityAnalyse<SysMenuEntity>(generatorConfig)
        val sysMenuClassModel = sysMenuEntityAnalyse.analyseClass(SysMenuEntity::class.java)
        context.sysMenuClassModel = sysMenuClassModel

        val sysApiEntityAnalyse = EntityAnalyse<SysApiEntity>(generatorConfig)
        val sysApiClassModel = sysApiEntityAnalyse.analyseClass(SysApiEntity::class.java)
        context.sysApiClassModel = sysApiClassModel

        val sysComponentEntityAnalyse = EntityAnalyse<SysComponentEntity>(generatorConfig)
        val sysComponentClassModel = sysComponentEntityAnalyse.analyseClass(SysComponentEntity::class.java)
        context.sysComponentClassModel = sysComponentClassModel

        // INFO: Zhouwx: 2025/8/15 写入并获取该Entity文件的uuid
        writeEntityFileUuid(context)

        val logFilePath = getLogFilePath(classModel)
        context.logFilePath = logFilePath

        // INFO: Zhouwx: 2025/8/19 当前类和log文件的中类进行比较
        compareClassModel(context)

        for (templateClass in templateClasses) {
            generateTemplateFile(templateClass, context)
        }

        // INFO: Zhouwx: 2025/8/15 同步表结构
        syncTable(context)

        // INFO: Zhouwx: 2025/8/27 同步菜单
        syncMenu(context)

        // INFO: Zhouwx: 2025/9/5 同步api接口
        syncApi(context)

        // INFO: Zhouwx: 2025/9/5 同步api接口和menu关联项
        syncApiMenu(context)

        // INFO: Zhouwx: 2025/9/5 同步api接口和menu关联项
        syncComponent(context)

        // INFO: Zhouwx: 2025/8/15 写生成日志到本地
        writeLog(context)
    }

    private fun syncComponent(context: SysGeneratorContext) {
        if (!generatorConfig.syncComponent) {
            logInfo("${context.classModel.entityClassName} 已关闭组件关联同步")
            return
        }

        if (context.lastClassModel.syncComponent) {
            logInfo("${context.classModel.entityClassName} 接口菜单关联在上次已经同步过了，不再同步")
            context.classModel.syncComponent = true
            return
        }

        val syncComponentCore = SyncComponentCore()
        syncComponentCore.syncComponent(context, generatorConfig)
    }

    private fun syncApiMenu(context: SysGeneratorContext) {
        if (!generatorConfig.syncApiMenu) {
            logInfo("${context.classModel.entityClassName} 已关闭接口菜单关联同步")
            return
        }

        if (context.lastClassModel.syncApiMenu) {
            logInfo("${context.classModel.entityClassName} 接口菜单关联在上次已经同步过了，不再同步")
            context.classModel.syncMenu = true
            return
        }

        val syncApiMenuCore = SyncApiMenuCore()
        syncApiMenuCore.syncApiMenu(context, generatorConfig)
    }

    private fun syncApi(context: SysGeneratorContext) {
        if (!generatorConfig.syncApi) {
            logInfo("${context.classModel.entityClassName} 已关闭接口同步")
            return
        }

        if (context.lastClassModel.syncMenu) {
            logInfo("${context.classModel.entityClassName} 接口在上次已经同步过了，不再同步")
            context.classModel.syncMenu = true
            return
        }

        val syncApiCore = SyncApiCore()
        syncApiCore.syncApi(context, generatorConfig)
    }

    private fun syncMenu(context: SysGeneratorContext) {
        if (!generatorConfig.syncMenu) {
            logInfo("${context.classModel.entityClassName} 已关闭菜单同步")
            return
        }

        if (context.lastClassModel.syncMenu) {
            logInfo("${context.classModel.entityClassName} 菜单在上次已经同步过了，不再同步")
            context.classModel.syncMenu = true
            return
        }

        val syncMenuCore = SyncMenuCore()
        syncMenuCore.syncMenu(context, generatorConfig)
    }
}